package database;

import java.io.FileWriter;
import java.io.IOException;

import datagraphics.Visitor;

/**
 * Pregunta con respuesta Numérica
 * @author Grupo 11 de Programacion Orientada a Objetos
 *
 */

public class NumericQuestion extends Question {

	private Double answer;
	private Double usrans;
	private final Double epsilon = 0.00001;
	
	/**
	 * Crea una instancia de NumericQuestion.
	 * @param answer - setea el número que
	 * representa la respuesta correcta a ésta
	 * pregunta
	 */
	
	public NumericQuestion(double answer) {
		super();
		this.answer = answer;
	}


	/**
	 * Devuelve la respuesta que valida como correcta
	 * @return Double - respuesta correcta
	 */
	
	public Double getAnswer() {
		return answer;
	}


	/**
	 * Establece la respuesta correcta
	 * @param answer - respuesta correcta
	 */
	
	public void setAnswer(Double answer) {
		this.answer = answer;
	}
	
	/**
	 * Retorna un hash de la pregunta
	 */
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + ((answer == null) ? 0 : answer.hashCode());
		return result;
	}
	
	/**
	 * Compara por igualdad semantica a dos preguntas
	 * de tipo NumericQuestion
	 * @param obj - Objeto contra el cual comparar
	 */
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		NumericQuestion other = (NumericQuestion) obj;
		if (answer == null) {
			if (other.answer != null)
				return false;
		} else if (Math.abs(answer - other.answer) > epsilon)
			return false;
		return true;
	}


	/**
	 * Devuelve true si la respuesta ingresada es correcta.
	 * La respuesta debe ser ingresada previamente con el metodo
	 * setUsrAns(Double usrans). Se considera como válida a la pregunta
	 * si la precisión entre la respuesta del usuario y la real no es mayor
	 * a un EPSILON = 0.00001
	 * @return - Un boolean que representa si la pregunta
	 * fue contestada exitosamente. En caso de no ser contestada
	 * se retorna false
	 */
	
	public boolean validAnswer() {
		boolean rta = false;
		
		if (usrans != null) {
			if (Math.abs(answer - usrans) > epsilon)
					rta = false;
			else
				rta = true;
		}
			
		
		return rta;
	}

	/** 
	 * Recibe una instancia de un Objecto que implementa
	 * la interfaz Visitor, el cual en conjunto con este método
	 * forman el Visitor Pattern, con el cual se logra independencia
	 * en la representación gráfica en pantalla de NumericQuestion
	 * @param visitor - instancia de un objeto que implementa Visitor
	 * y se encarga de la representación gráfica de NumericQuestion
	 */
	
	public void accept(Visitor visitor) {
		visitor.visit(this);
		return;
	}


	/**
	 * Develve la respuesta dada por el usuario
	 * @return Double - respuesta del usuario.
	 */
	public Double getUsrAns() {
		return usrans;
	}


	/**
	 * Almacena la respuesta dada por el usuario
	 * @param usrans - respuesta del usuario
	 */
	public void setUsrAns(Double usrans) {
		this.usrans = usrans;
	}
	
	/**
	 * Representa textualmente a NumericQuestion
	 * completamente cualificada por nombre de clase
	 * concreta, texto de la pregunta y puntaje
	 */
	
	@Override
	public String toString() {
		String classname, qtext, scr;
		
		classname = "NumericQuestion"; // MARK
		qtext = this.getQuestionText();
		scr = String.valueOf(this.getScore());
		
		return (classname + " - " + qtext + " - " + scr);
	}


	/**
	 * Descarga en archivo a NumericQuestion
	 * @param fw - Instancia de FileWriter que contiene
	 * el archivo en donde debe salvarse a si misma.
	 * @throws IOException
	 */
	
	@Override
	public void saveToFile(FileWriter fw) throws IOException {
		fw.write("2");
		fw.write("\n");
		fw.write(String.valueOf(this.getLevel()));
		fw.write("\n");
		fw.write("1"); // 1 opcion
		fw.write("\n");
		fw.write("1"); // Unica respuesta valida
		fw.write("\n");
		fw.write(this.getQuestionText());
		fw.write("\n");
		fw.write(String.valueOf(this.answer));
		fw.write("\n");
		fw.write(String.valueOf(this.answer));
		fw.write("\n");
		fw.write(String.valueOf(this.getScore()));
		return;
	}
		
}
